package com.paradogs.framework.core.netty;

import com.paradogs.framework.core.utils.SpringUtils;
import io.netty.channel.*;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.LengthFieldBasedFrameDecoder;
import io.netty.handler.codec.LengthFieldPrepender;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;

/**
 * @author: yumi
 * @date: 2023/2/18  13:14
 * @Description: TODO
 */
@Slf4j
public abstract class PRAbChannelInitializer extends ChannelInitializer<NioSocketChannel> {

    @Autowired
    private ProtocolProperties protocolProperties;

    private PRAbMsgHandler msgHandler;

    public PRAbChannelInitializer(PRAbMsgHandler msgHandler) {
        this.msgHandler = msgHandler;
    }

    /**
     * 建立连接，初始化通道（还不能传输消息）
     * @param channel
     * @throws Exception
     */
    @Override
    protected void initChannel(NioSocketChannel channel) throws Exception {

        channel.pipeline().addLast(new LengthFieldBasedFrameDecoder(
                protocolProperties.getMaxFrameLength(),
                protocolProperties.getLengthFieldOffset(),
                protocolProperties.getLengthFieldLength(),
                protocolProperties.getLengthAdjustment(),
                protocolProperties.getInitialBytesToStrip()));

        channel.pipeline().addLast(new LengthFieldPrepender(protocolProperties.getLengthFieldLength()));

        channel.pipeline().addLast(SpringUtils.getBean(PRCodec.class));

        channel.pipeline().addLast(msgHandler);

    }

    /**
     * ChannelInitializer 的 ChannelActive 和 ChannelInboundHandlerAdapter 的不一样，一般用 ChannelInboundHandlerAdapter
     * ChannelInitializer.ChannelActive 会不触发
     */

    /**
     * ChannelInitializer 的异常处理
     * @param ctx
     * @throws Exception
     */
    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        cause.printStackTrace();
        log.error("{}", cause.getMessage());
    }

}
